#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import logging
from flask import(
    Flask, g
)

from sqlalchemy.exc import InternalError

from fx.lib.session import RedisSessionInterface
from flask.sessions import SecureCookieSessionInterface

from fx.lib.log import enable_logging
from fx.lib.fx_celery import app_celery
from fx.common.base_redis import rdb
from fx.configs import CONFIG_MAPPING
from fx.models import db
# from fx.utils.user import get_current_admin_user

_app_instances = dict()


class FxAPP(Flask):

    def register_app_config(self, config_str):
        c = CONFIG_MAPPING.get(config_str)
        self.config.from_object(c())

    def register_app_database(self):
        db.init_app(self)
        rdb.init_app(self)
        db.app = self

    def init_celery(self):
        app_celery.init_app(self)

    def register_app_routes(self):
        if self.is_api:
            from fx.apps.api import register_routes
        # elif self.is_crm:
        #     from .crm import register_routes
        # else:
        #     from .admin import register_routes
        register_routes(self)

    def register_hooks(self):
        # @self.before_request
        # def load_current_user():
        #     if self.is_admin:
        #         g.user = get_current_admin_user()
        pass

    def register_app_error_handlers(self):
        def sqlalchemy_internalerror_handler(error):
            db.session.remove()
            raise error
        self.register_error_handler(InternalError, sqlalchemy_internalerror_handler)
        if self.is_api:
            from fx.apps.api import register_error_handlers
        # elif self.is_crm:
        #     from .crm import register_error_handlers
        # else:
        #     from .admin import register_error_handlers
        register_error_handlers(self)

    def register_resources(self):
        if self.is_api:
            from fx.apps.api import register_resources
        # elif self.is_crm:
        #     from .crm import register_resources
        # else:
        #     from .admin import register_resources
        register_resources(self)

    def register_http_session(self):
        if not self.is_admin:
            self.session_interface = RedisSessionInterface(redis=rdb, prefix="fx_session:")  # 设置 session
        else:
            self.session_interface = SecureCookieSessionInterface()

    @property
    def is_local(self):
        return self.config.get('RUN_ENV').lower() == 'local'

    @property
    def is_prod(self):
        return self.config.get('RUN_ENV').lower() == 'prod'

    @property
    def is_dev(self):
        return self.config.get('RUN_ENV').lower() == 'dev'

    @property
    def is_crm(self):
        return self.config.get('PROJECT').lower() == 'crm'

    @property
    def is_api(self):
        return self.config.get('PROJECT').lower() == 'api'

    @property
    def is_admin(self):
        return self.config.get('PROJECT').lower() == 'admin'

    def init_loggers(self):
        for k, v in self.config['LOGGERS'].items():
            logger = logging.getLogger(k)
            l = v.get("level")
            file = v.get("file")
            logger.setLevel(getattr(logging, l.upper(), logging.INFO))
            enable_logging(logger, file)


def create_app():
    config = os.environ.get('RUN_ENV', '')
    if not config:
        config = 'local.api'
    if config not in CONFIG_MAPPING:
        raise Exception("CONFIG ERROR")
    app = _app_instances.get(config, {}).get('app', None)
    if app:
        return app
    app = FxAPP(__name__)
    app.register_app_config(config)
    app.init_loggers()
    app.register_app_database()
    app.register_app_routes()
    app.register_resources()
    app.register_hooks()
    app.register_app_error_handlers()
    app.register_http_session()
    app.init_celery()
    _app_instances[config] = {}
    _app_instances[config]['app'] = app
    return app
